/**
 * Copyright (c) 2016-2019, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.hg.jfsa.web.theme;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.jfinal.kit.PathKit;
import com.jfinal.kit.Prop;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;

import cn.hg.base.common.BaseConstants;

public final class Theme {

	private static Log log = Log.getLog(Theme.class);
	private static final String THEME_H5_SUFFIX = "_h5.html";
	private static final String THEME_SEPARATOR = "_";
	private String author;
	private String authorWebsite;
	private String description;
	private Map<Integer, String> errorViewMap = new HashMap<>();
	private String folder;
	private List<String> htmls = new ArrayList<>();
	private String id;
	private String optionsFile;
	private String optionsPage;
	private Properties propertis = new Properties();
	private List<String> screenshots;
	private String title;
	private String updateUrl;
	private String version;
	private int versionCode;

	public Theme (String configFilePath) {
		File configFile = new File(configFilePath);
		Prop prop = new Prop(configFile, "utf-8");
		this.folder = configFile.getParentFile().getName();
		this.id = prop.get("id");
		this.title = prop.get("title");
		this.description = prop.get("description");
		this.author = prop.get("author");
		this.authorWebsite = prop.get("authorWebsite");
		this.version = prop.get("version");
		this.updateUrl = prop.get("updateUrl");
		this.screenshots = new ArrayList<>();
		this.optionsFile = prop.get("optionsFile");
		this.optionsPage = prop.get("optionsPage");

		if (StrKit.notBlank(prop.get("screenshots"))) {
			String[] scrs = prop.get("screenshots").split(",");

			for (String s : scrs) {
				this.screenshots.add(this.getWebAbsolutePath() + "/" + s);
			}

		}

		// 从主题的配置文件中读取错误页面信息
		String error401view = prop.get("error401view");

		if (StrKit.notBlank(error401view)) {
			this.errorViewMap.put(401, error401view);
		}

		String error403view = prop.get("error403view");

		if (StrKit.notBlank(error403view)) {
			this.errorViewMap.put(403, error403view);
		}

		String error404view = prop.get("error404view");

		if (StrKit.notBlank(error404view)) {
			this.errorViewMap.put(404, error404view);
		}

		String error500view = prop.get("error500view");

		if (StrKit.notBlank(error500view)) {
			this.errorViewMap.put(500, error500view);
		}

		String errorView = prop.get("errorView");

		if (StrKit.notBlank(error401view)) {
			this.errorViewMap.put(0, errorView);
		}

		String vcode = prop.get("versionCode");
		this.versionCode = StrKit.isBlank(vcode) ? 1 : Integer.valueOf(vcode);

		// 如果存在配置文件，则从配置文件中读取信息，配置文件为Properties格式
		if (StrKit.notBlank(this.optionsFile)) {

			try {
				this.propertis.load(new FileReader(this.getAbsolutePath() + this.optionsFile));
			}
			catch (IOException e) {
				Theme.log.error("主题加载错误：", e);
			}

		}

		String[] files = configFile
			.getParentFile()
			.list( (dir, name) -> name.endsWith(".html"));
		this.htmls.addAll(Arrays.asList(files));
	}

	void setFolder (String folder) { this.folder = folder; }

	void updateOptions (Map<String, String> optionMap) {

		if (StrKit.isBlank(this.getOptionsFile())) {
			return;
		}

		// 更新参数表
		this.propertis.putAll(optionMap);
		// 更新Options文件
		String optionFileName = this.getAbsolutePath() + this.getOptionsFile();
		File of = new File(optionFileName);
		FileWriter fw = null;

		if (of.exists() && of.isFile()) {

			try {
				fw = new FileWriter(of);
				this.propertis.store(fw, this.getTitle() + "：参数配置");
			}
			catch (IOException e) {
				Theme.log.warn("更新主题参数出错！", e);
			}
			finally {

				if (fw != null) {

					try {
						fw.close();
					}
					catch (IOException e) {
						Theme.log.warn("更新主题参数出错！", e);
					}

				}

			}

		}

	}

	public String getAbsolutePath () { return PathKit.getWebRootPath() + BaseConstants.THEME_PATH + "/" + this.folder; }

	public String getAuthor () { return this.author; }

	public String getAuthorWebsite () { return this.authorWebsite; }

	public String getDescription () { return this.description; }

	public Map<Integer, String> getErrorViewMap () { return this.errorViewMap; }

	public String getFolder () { return this.folder; }

	public String getId () { return this.id; }

	public String getOption (String key) {
		return this.propertis.getProperty(key);
	}

	public String getOptionsFile () { return this.optionsFile; }

	public String getOptionsPage () { return this.optionsPage; }

	public List<String> getScreenshots () { return this.screenshots; }

	public String getTitle () { return this.title; }

	public String getUpdateUrl () { return this.updateUrl; }

	public String getVersion () { return this.version; }

	public int getVersionCode () { return this.versionCode; }

	public String getWebAbsolutePath () { return BaseConstants.THEME_PATH + "/" + this.folder; }

	/**
	 * 找出可以用来渲染的 html 模板
	 *
	 * @param theme
	 *
	 * @return
	 */
	public String matchThemeFile (String theme, boolean isMoblieBrowser) {

		if (isMoblieBrowser) {
			int indexOf = theme.indexOf(".");
			theme = theme.substring(0, indexOf) + Theme.THEME_H5_SUFFIX;
		}

		if (this.htmls.contains(theme)) {
			return theme;
		}

		int lastIndex = theme.lastIndexOf(Theme.THEME_SEPARATOR);

		if (lastIndex <= 0) {
			return null;
		}

		// 手机浏览器，优先去找_h5的模板进行渲染
		if (isMoblieBrowser) {
			String h5Theme = this.matchH5Theme(theme);

			if (h5Theme != null) {
				return h5Theme;
			}

		}

		while (lastIndex > 0) {
			theme = theme.substring(0, lastIndex) + ".html";

			if (this.htmls.contains(theme)) {
				return theme;
			}

			lastIndex = theme.lastIndexOf(Theme.THEME_SEPARATOR);
		}

		return this.htmls.contains(theme) ? theme : null;
	}

	/**
	 * 只匹配 h5 的模板 ，如果匹配不到 h5 ，返回 null
	 * <p>
	 * 例如：
	 * 需要 aa_bb_cc_dd_h5.html
	 * 寻找的顺序是：aa_bb_cc_h5.html -> aa_bb_h5.html -> aa_h5.html
	 *
	 * @param theme
	 *
	 * @return
	 */
	private String matchH5Theme (String theme) {
		// TODO:
		// while (StrExtKit.countMatches(theme, '_') > 1) {
		//
		// int sLastIndex = StrExtKit.lastOrdinalIndexOf(theme, "_", 2);
		// theme = theme.substring(0, sLastIndex) + "_h5.html";
		//
		// if (htmls.contains(theme)) {
		// return theme;
		// }
		// }
		return this.htmls.contains(theme) ? theme : null;
	}

}
